package com.ews.onlineexchange.rest;
import java.io.File;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Date;
import java.util.List;

import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.transaction.Transactional;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;

import org.apache.commons.lang3.StringUtils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ews.onlineexchange.app.AppService;
import com.ews.onlineexchange.app.CustomMapper;
import com.ews.onlineexchange.app.RatedTradeListForApp;
import com.ews.onlineexchange.app.SupplierAppliedTradeListForApp;
import com.ews.onlineexchange.app.SupplierSuccessTradeListForApp;
import com.ews.onlineexchange.app.SupplierUnapplyTradeListForApp;
import com.ews.onlineexchange.app.entity.SimpleBulletinTrade;
import com.ews.onlineexchange.app.entity.SimpleTradeTradeRating;
import com.ews.onlineexchange.app.entity.TempTrade;
import com.ews.onlineexchange.model.Attachment;
import com.ews.onlineexchange.model.Bulletin;
import com.ews.onlineexchange.model.ChooseType;
import com.ews.onlineexchange.model.RequirementDefination;
import com.ews.onlineexchange.model.Trade;
import com.ews.onlineexchange.model.TradeReportData;
import com.ews.onlineexchange.model.bulletinRequirement.Requirement;
import com.ews.onlineexchange.service.DeterminedRecordService;
import com.ews.onlineexchange.service.SmsService;
import com.ews.onlineexchange.service.TradeHome;
import com.ews.onlineexchange.service.TradeService;
import com.ews.onlineexchange.util.AttachmentType;
import com.ews.onlineexchange.util.AttachmentUtils;
import com.ews.onlineexchange.util.RestParamUtil;

/**
 * 消息通知接口
 * @author
 *
 */
@Path(value = "/trade")
@Transactional
public class TradeRest {
	
	@Inject
	SupplierUnapplyTradeListForApp  supplierUnapplyTradeListForApp;
	
	@Inject
	TradeHome tradeHome;
	
	@Inject
	AppService appService;
	
	@Inject
	EntityManager entityManager;
	
	@Inject
	DeterminedRecordService recordService;
	
	@Inject
	SmsService smsService;
	
	@Inject
	SupplierAppliedTradeListForApp  supplierAppliedTradeListForApp;
	
	@Inject
	SupplierSuccessTradeListForApp supplierSuccessTradeListForApp;
	
	@Inject
	RatedTradeListForApp ratedTradeListForApp;
	
	@Inject
	TradeService tradeService;
	
	@Inject
	AttachmentUtils attachmentUtils;

	@GET
	@Path("/getUnappledTradeList/{pageNumber}/{pageSize}/{userId}/{projectName}/{serialNumber}")
	@Produces("text/html; charset=UTF-8")
	@Context
	public String getUnappledBulletinList(@PathParam("pageNumber") int pageNumber,@PathParam("pageSize")int pageSize,@PathParam("userId") String userId,
			@PathParam("projectName") String projectName,@PathParam("serialNumber") String serialNumber) throws Exception{        
        CustomMapper mapper = new CustomMapper();
        supplierUnapplyTradeListForApp.refresh();
        supplierUnapplyTradeListForApp.setFirstResult((pageNumber-1) * pageSize);
        supplierUnapplyTradeListForApp.setMaxResults(pageSize);
        supplierUnapplyTradeListForApp.setApp_userId(userId);
        supplierUnapplyTradeListForApp.setProjectName(RestParamUtil.getParamValue(projectName));
        System.out.println(RestParamUtil.getParamValue(serialNumber));
        supplierUnapplyTradeListForApp.setSerialNumber(RestParamUtil.getParamValue(serialNumber));
        Long totalcount = supplierUnapplyTradeListForApp.getResultCount();
        List<Trade> tradeList = supplierUnapplyTradeListForApp.getResultList();
        List<SimpleBulletinTrade> sBulletinTradeList = appService.getSimpleBulletinList(tradeList);
        JSONObject jsonnObject = new JSONObject();
        jsonnObject.put("totalcount", totalcount);
        jsonnObject.put("bulletinTradeArr", sBulletinTradeList);
		return mapper.writeValueAsString(jsonnObject);
	}
	
	@POST
	@Path("/applyTrade/{userId}/{tradeId}")
	@Produces("text/html; charset=UTF-8")
	@Context
	public String applyTrade(@PathParam("userId") String userId,@PathParam("tradeId") String tradeId) throws Exception {
        String result = appService.applyTrade(userId, tradeId);
		return result;
	}

	@GET
	@Path("/getAppliedTradeList/{pageNumber}/{pageSize}/{userId}/{projectName}/{serialNumber}")
	@Produces("text/html; charset=UTF-8")
	@Context
	public String getAppliedTradeList(@PathParam("pageNumber") int pageNumber,@PathParam("pageSize")int pageSize,@PathParam("userId") String userId,
			@PathParam("projectName") String projectName,@PathParam("serialNumber") String serialNumber) throws Exception{        
        CustomMapper mapper = new CustomMapper();
        supplierAppliedTradeListForApp.refresh();
        supplierAppliedTradeListForApp.setFirstResult((pageNumber-1) * pageSize);
        supplierAppliedTradeListForApp.setMaxResults(pageSize);
        supplierAppliedTradeListForApp.setApp_userId(userId);
        supplierAppliedTradeListForApp.setProjectName(RestParamUtil.getParamValue(projectName));
        supplierAppliedTradeListForApp.setSerialNumber(RestParamUtil.getParamValue(serialNumber));
        Long totalcount = supplierAppliedTradeListForApp.getResultCount();
        List<Trade> tradeList = supplierAppliedTradeListForApp.getResultList();
        List<SimpleBulletinTrade> sBulletinTradeList = appService.getSimpleBulletinList(tradeList);
        JSONObject jsonnObject = new JSONObject();
        jsonnObject.put("totalcount", totalcount);
        jsonnObject.put("bulletinTradeArr", sBulletinTradeList);
		return mapper.writeValueAsString(jsonnObject);
	}
	
	@GET
	@Path("/getTradeById")
	@Produces("application/json")
	@Context
	public TempTrade getTradeById(@QueryParam("tradeId") String tradeId) throws Exception{
		tradeHome.setId(tradeId);
		return appService.getTempTradeByTrade(tradeHome.getInstance());
	}
	
	@POST
	@Path("/cancelTrade/{tradeId}")
	@Produces("text/html; charset=UTF-8")
	@Context
	public String cancelTrade(@PathParam("tradeId") String tradeId) throws Exception {
	        String result = appService.cancelTrade( tradeId);
			return result;
	}
	
	@GET
	@Path("/getSuccessTradeList/{pageNumber}/{pageSize}/{userId}/{projectName}/{serialNumber}")
	@Produces("text/html; charset=UTF-8")
	@Context
	public String getSuccessTradeList(@PathParam("pageNumber") int pageNumber,@PathParam("pageSize")int pageSize,@PathParam("userId") String userId,
			@PathParam("projectName") String projectName,@PathParam("serialNumber") String serialNumber) throws Exception{        
        CustomMapper mapper = new CustomMapper();
        supplierSuccessTradeListForApp.refresh();
        supplierSuccessTradeListForApp.setFirstResult((pageNumber-1) * pageSize);
        supplierSuccessTradeListForApp.setMaxResults(pageSize);
        supplierSuccessTradeListForApp.setApp_userId(userId);
        supplierSuccessTradeListForApp.setProjectName(RestParamUtil.getParamValue(projectName));
        supplierSuccessTradeListForApp.setSerialNumber(RestParamUtil.getParamValue(serialNumber));
        Long totalcount = supplierSuccessTradeListForApp.getResultCount();
        List<Trade> tradeList = supplierSuccessTradeListForApp.getResultList();
        List<SimpleBulletinTrade> sBulletinTradeList = appService.getSimpleBulletinList(tradeList);
        JSONObject jsonnObject = new JSONObject();
        jsonnObject.put("totalcount", totalcount);
        jsonnObject.put("bulletinTradeArr", sBulletinTradeList);
		return mapper.writeValueAsString(jsonnObject);
	}
	
	@GET
	@Path("/getRatedTradeList/{pageNumber}/{pageSize}/{userId}/{projectName}/{serialNumber}")
	@Produces("application/json")
	@Context
	public JSONObject getRatedTradeList(@PathParam("pageNumber") int pageNumber,@PathParam("pageSize")int pageSize,@PathParam("userId") String userId,
			@PathParam("projectName") String projectName,@PathParam("serialNumber") String serialNumber) throws Exception{   
        ratedTradeListForApp.refresh();
        ratedTradeListForApp.setFirstResult((pageNumber-1) * pageSize);
        ratedTradeListForApp.setMaxResults(pageSize);
        ratedTradeListForApp.setApp_userId(userId);
        ratedTradeListForApp.setProjectName(RestParamUtil.getParamValue(projectName));
        ratedTradeListForApp.setSerialNumber(RestParamUtil.getParamValue(serialNumber));
        Long totalcount = ratedTradeListForApp.getResultCount();
        List<Trade> tradeList = ratedTradeListForApp.getResultList();
        
        List<SimpleTradeTradeRating> sBulletinTradeList = appService.getSimpleTradeRatingList(tradeList);
        JSONObject jsonnObject = new JSONObject();
        jsonnObject.put("totalcount", totalcount);
        jsonnObject.put("bulletinTradeArr", sBulletinTradeList);
		return jsonnObject;
	}
	
	@POST
	@Path("/offerPrice")
	@Produces("application/json")
	@Context
	public JSONObject updateOfferPrice(@QueryParam("tradeId") String tradeId,@QueryParam("price")BigDecimal price) {   
		JSONObject json = new JSONObject();
		int status  = 200;
		String errMsg = "";
		Trade trade = tradeService.getTradeById(tradeId);		
		if(trade == null) {
			status = 500;
			errMsg = "根据tradeId，未找到相关的Trade,请稍后重试！";
		}else {//更新报价
			try {
				if(price == null) throw new RuntimeException();
				if(trade.getOfferCount() >= 3) {
					status = 500;
					errMsg = "报价失败，您的报价次数已经超过三次！";
				}else {
					tradeService.updateOfferPrice(trade, price);
				}
				
			} catch (Exception e) {
				status = 500;
				errMsg = "报价失败，请联系管理员！";
			}
		}
		json.put("price", price);
		json.put("status", status);
		json.put("errMsg", errMsg);
		return json;
	}
	
	@GET
	@Path("/getNewestPrice")
	@Produces("application/json")
	@Context
	public JSONObject getNewestPrice(@QueryParam("tradeId") String tradeId) {   
		JSONObject json = new JSONObject();
		int status  = 200;
		String errMsg = "";
		Trade trade = tradeService.getTradeById(tradeId);		
		if(trade == null) {
			status = 500;
			errMsg = "获取最新报价失败，请联系管理员！";
		}else {
			json.put("price", trade.getOffer());
		}
		
		json.put("status", status);
		json.put("errMsg", errMsg);
		return json;
	}
	
	@POST
	@Path("/apply")
	@Produces(MediaType.APPLICATION_JSON)
	public JSONObject apply(@FormParam("supplierId") String supplierId,@FormParam("tradeId") String tradeId,@FormParam("defsStr") String defsStr,@FormParam("offer") BigDecimal offer) {
		JSONObject json = new JSONObject();
		String message = "";
		int status = 500;
		if(recordService.isExistSupplierInRecord(supplierId)) {
			message = "你公司参与项目选取资格已被暂停，待整改合格并提报诚信承诺书后，恢复项目选取资格。";
		}
		if(StringUtils.isBlank(tradeId)) tradeId = "";
		Trade trade = entityManager.find(Trade.class, tradeId);
		if(trade == null) {
			message = "未找到相应的交易，请检查参数是否正确！";
		}else {
			try {
				Bulletin bulletin = trade.getBulletin();
				
				if(ChooseType.Best.equals(bulletin.getWayOfChoose())) {
					if(offer == null) {
						json.put("message", "当为择优选取时，需要填写报价！");
						json.put("status", status);
						return json;
					}else {
						TradeReportData tradeReportData = new TradeReportData();
						tradeReportData.setOffer(offer);
						trade.setTradeReportData(tradeReportData);
					}
				}	
				//报名要求解析
				List<RequirementDefination> defs = trade.getBulletin().getDefs();
				
				boolean validate = true;
				
				StringBuilder validateMsg = new StringBuilder();
				List<Requirement> requirements = new ArrayList<>();
				if(defs.size() > 0) {
					for (RequirementDefination def : defs) {
						String requireName = def.getRequiredName();
						boolean required = def.isRequired();
						String defId = def.getId();
						String jsonArrayStr = getJsonArrayStrByDefId(defId,defsStr);
						List<Attachment> attachments = new ArrayList<>();
						if(required) {//必填
							if(StringUtils.isBlank(jsonArrayStr)) {
								validate = false;
								validateMsg.append(requireName) 
											.append("必须上传相应的附件；");
							}else {
								if(jsonArrayStr != null)
								attachments =	getAttachmentListFromJsonArrayStr(jsonArrayStr);
							}
						}else {
							if(StringUtils.isNotBlank(jsonArrayStr)) {
								attachments =	getAttachmentListFromJsonArrayStr(jsonArrayStr);
							}
						}
						Requirement requiremnt = new Requirement();
						requiremnt.setAttachments(attachments);
						requiremnt.setRequirementDefination(def);
						requirements.add(requiremnt);
					}
					trade.setRequirements(null);
					if(validate) {
//						bulletin.setHasAppliedCount(bulletin.getAppliedCount()+1);				
						trade.setApply(true);
						trade.setApplyTime(new Date());
						trade.setHasVerify(true);
						trade.setVerifyTime(new Date());
						trade.setRequirements(requirements);
						entityManager.merge(bulletin);
						applyAndSaveTrade(trade);
						message = "报名成功!";
						if(bulletin.getWayOfChoose().equals(ChooseType.Average) || bulletin.getWayOfChoose().equals(ChooseType.Price)){
							message += "请于选取时间截止前登录系统按照操作提示进行报价。";
						}
						status = 200;
					}else message = validateMsg.toString();
				}else {
//					bulletin.setHasAppliedCount(bulletin.getAppliedCount()+1);				
					trade.setApply(true);
					trade.setApplyTime(new Date());
					trade.setHasVerify(true);
					trade.setVerifyTime(new Date());
					entityManager.merge(bulletin);
					applyAndSaveTrade(trade);
					message = "报名成功!";
					if(bulletin.getWayOfChoose().equals(ChooseType.Average) || bulletin.getWayOfChoose().equals(ChooseType.Price)){
						message += "请于选取时间截止前登录系统按照操作提示进行报价。";
					}
					status = 200;
					
				}
				
			} catch (Exception e) {
				e.printStackTrace();
				message = "报名出现错误，请稍后重试！";
				status = 500;
			}
		}
		json.put("message", message);
		json.put("status", status);
		return json;
	}
	
	public void applyAndSaveTrade(Trade trade) {
		entityManager.merge(trade);
		smsService.addSuccessAppliedMessageToSupplier(trade);
	}
	
	public String getJsonArrayStrByDefId(String defId,String defsStr) {
		JSONObject json = JSONObject.parseObject(defsStr);
		if(json == null) return "";
		else return json.getString(defId);
	}
	public List<Attachment> getAttachmentListFromJsonArrayStr(String jsonArrayStr) throws Exception {
		JSONArray subjectIdPhotosArr = JSONArray.parseArray(jsonArrayStr);
		List<Attachment> attachments = new ArrayList<>();
		for (Object obj : subjectIdPhotosArr) {
			String jsonStr = JSONObject.toJSONString(obj);
			Attachment attr = getAttachmentFromJsonStr(jsonStr);
			attachments.add(attr);
		}
		return attachments;
	}
	
	public Attachment getAttachmentFromJsonStr(String jsonStr) throws Exception {
		JSONObject jsonObj = JSONObject.parseObject(jsonStr);
		String  fileName = jsonObj.getString("fileName");
		long 	size    = jsonObj.getLongValue("size");
		String dataAttachmentString = jsonObj.getString("result");
		byte[] data = Base64.getDecoder().decode(dataAttachmentString.substring(dataAttachmentString.indexOf(",") + 1));
		Attachment attr = new Attachment();
		JSONObject fileInfo = attachmentUtils.getFileInfo(fileName,AttachmentType.Image, null);
		String diskFileName = fileInfo.getString("diskFileName");
		String filepath = fileInfo.getString("filepath");
		attr.setFilepath(filepath);
		attr.setDiskFileName(diskFileName);
		attr.setFilename(fileName);
		attr.setFilesize(size);
		attachmentUtils.saveFileToDisk(filepath, data);
		return attr;
	}
	
	@GET    
    @Produces(MediaType.APPLICATION_OCTET_STREAM)
	@Path( value = "/archive/{id}" )
	public Response archive( @PathParam( "id" ) String id ) {
		File zipFile = tradeService.archive( id );
		
		ResponseBuilder response = Response.ok( zipFile );
		response.header("Content-Disposition", "attachment; filename=\"" + id + ".zip\"");
		return response.build();
	}
	
}



